﻿using System;
using System.Collections.Generic;

using System.Windows.Controls;

using GameLibrary.Interfaces;
using GameLibrary.Settlement;
using GameLibrary.Unit;

namespace UserInterface.Helpers
{
    using Commands.Settlement;
    using Commands.Unit;
    using Commands.Game;
    using Commands.Information;

    public static class ContextMenuCreator
    {
        public static uint PlayerID { get; set; }
        public static ContextMenu GetContextMenu(IInfo objectNeedsContextMenu)
        {
            if (objectNeedsContextMenu is SettlementInfo)
                return CreateContextMenuForSettlement(objectNeedsContextMenu as SettlementInfo);
            else
                if (objectNeedsContextMenu is UnitInfo)
                    return CreateContextMenuForUnit(objectNeedsContextMenu as UnitInfo);
                else
                    throw new ArgumentException("Wrong info type which not exist in game.");

        }

        public static ContextMenu GetContextMenuForItems(IEnumerable<IInfo> listOfItems)
        {
            ContextMenu menu = new ContextMenu();
            foreach (var item in listOfItems)
                menu.Items.Add(GetMenuItemForOneItem(item));
            return menu;
        }

        private static MenuItem GetMenuItemForOneItem(IInfo item)
        {
            MenuItem menu = new MenuItem();
            menu.Header = item.ID.ToString();
            UnitInfo unit = item as UnitInfo;

            if (item.OwnerID == PlayerID)
            {
                menu.Items.Add(GetMoveMenuItem(unit));
                menu.Items.Add(GetAttackMenuItem(unit));
                menu.Items.Add(GetFortifyMenuItem(unit));
                menu.Items.Add(GetUpgradeMenuItem(unit));
                if (unit.Template.Actions.HasFlag(UnitActionFlags.Build) == true)
                    menu.Items.Add(GetBuildMenuItem(unit));
                if (unit.Template.Actions.HasFlag(UnitActionFlags.Explore) == true)
                    menu.Items.Add(GetExploreMenuItem(unit));
                menu.Items.Add(GetDisbandMenuItem(unit));
            }
            menu.Items.Add(GetUnitInfoMenuItem(unit));

            return menu;
        }

        #region tile

        public static ContextMenu GetContextMenuForTile(GameLibrary.Tile.TileType tile)
        {
            ContextMenu menu = new ContextMenu();
            menu.Items.Add(GetTileInfoMenuItem(tile));
            return menu;
        }

        private static MenuItem GetTileInfoMenuItem(GameLibrary.Tile.TileType tile)
        {
            MenuItem item = new MenuItem();
            item.Header = "Info";
            item.Command = ShowTileInfoCommand.ShowTileInfo;
            item.CommandParameter = tile;
            return item;
        }

        #endregion

        #region settlement context menu

        private static ContextMenu CreateContextMenuForSettlement(SettlementInfo settlement)
        {
            ContextMenu menu = new ContextMenu();
            if (PlayerID == settlement.OwnerID)
            {
                menu.Items.Add(GetBuildBuildingMenuItem(settlement));
                menu.Items.Add(GetLinkToCityMenuItem(settlement));
                menu.Items.Add(GetChangeTypeMenuItem(settlement));
                menu.Items.Add(GetAbandonMenuItem(settlement));
            }
            menu.Items.Add(GetSettlementInfoMenuItem(settlement));
            return menu;
        }
        private static MenuItem GetSettlementInfoMenuItem(SettlementInfo settlement)
        {
            MenuItem info = new MenuItem();
            info.Header = "Show Info";
            info.Command = ShowSettlementInfoCommand.ShowSettlementInfo;
            info.CommandParameter = settlement;
            return info;
        }
        private static MenuItem GetBuildBuildingMenuItem(SettlementInfo settlement)
        {
            MenuItem build = new MenuItem();
            build.Header = "Build Buildings";
            build.Items.Add(GetBuildRoadMenuItem(settlement));
            switch (settlement.Type)
            {
                case SettlementFlags.City:
                    build.Items.Add(GetBuildFactoryMenuItem(settlement));
                    break;
                case SettlementFlags.Village:
                    build.Items.Add(GetBuildPlantMenuItem(settlement));
                    break;
            }
            return build;
        }

        private static MenuItem GetBuildRoadMenuItem(SettlementInfo settlement)
        {
            MenuItem road = new MenuItem();
            road.Header = "Build Road";
            road.Command = BuildRoadCommand.BuildRoad;
            road.CommandParameter = settlement;
            return road;
        }
        private static MenuItem GetBuildPlantMenuItem(SettlementInfo settlement)
        {
            MenuItem plant = new MenuItem();
            plant.Header = "Build Plant";
            plant.Command = BuildPlantCommand.BuildPlant;
            plant.CommandParameter = settlement;
            return plant;
        }
        private static MenuItem GetBuildFactoryMenuItem(SettlementInfo settlement)
        {
            MenuItem factory = new MenuItem();
            factory.Header = "Build Factory";
            factory.Command = BuildFactoryCommand.BuildFactory;
            factory.CommandParameter = settlement;
            return factory;
        }
        private static MenuItem GetLinkToCityMenuItem(SettlementInfo settlement)
        {
            MenuItem link = new MenuItem();
            link.Header = "Link To City";
            link.Command = LinkToCityCommand.LinkToCity;
            link.CommandParameter = settlement;
            switch (settlement.Type)
            {
                case SettlementFlags.City:
                    link.IsEnabled = false;
                    break;
                case SettlementFlags.Village:
                    link.IsEnabled = true;
                    break;
            }
            return link;
        }

        private static MenuItem GetChangeTypeMenuItem(SettlementInfo settlement)
        {
            MenuItem changeType = new MenuItem();
            switch (settlement.Type)
            {
                case SettlementFlags.City:
                    changeType.Header = "Change Type To Village";
                    break;
                case SettlementFlags.Village:
                    changeType.Header = "Change Type To City";
                    break;
            }

            changeType.Command = ChangeTypeCommand.ChangeType;
            changeType.CommandParameter = settlement;
            return changeType;
        }
        private static MenuItem GetAbandonMenuItem(SettlementInfo settlement)
        {
            MenuItem abandon = new MenuItem();
            switch (settlement.Type)
            {
                case SettlementFlags.City:
                    abandon.Header = "Abandon City";
                    break;
                case SettlementFlags.Village:
                    abandon.Header = "Abandon Village";
                    break;
            }
            abandon.Command = AbandonCommand.Abandon;
            abandon.CommandParameter = settlement;
            return abandon;
        }
        #endregion

        #region unit context

        private static ContextMenu CreateContextMenuForUnit(UnitInfo unit)
        {
            ContextMenu menu = new ContextMenu();
            if (unit.OwnerID == PlayerID)
            {
                menu.Items.Add(GetMoveMenuItem(unit));
                menu.Items.Add(GetAttackMenuItem(unit));
                menu.Items.Add(GetFortifyMenuItem(unit));
                menu.Items.Add(GetUpgradeMenuItem(unit));
                if (unit.Template.Actions.HasFlag(UnitActionFlags.Build) == true)
                    menu.Items.Add(GetBuildMenuItem(unit));
                if (unit.Template.Actions.HasFlag(UnitActionFlags.Explore) == true)
                    menu.Items.Add(GetExploreMenuItem(unit));
                menu.Items.Add(GetDisbandMenuItem(unit));
            }
            menu.Items.Add(GetUnitInfoMenuItem(unit));
            return menu;
        }

        private static MenuItem GetUnitInfoMenuItem(UnitInfo unit)
        {
            MenuItem info = new MenuItem();
            info.Header = "Show Info";
            info.Command = ShowUnitInfoCommand.ShowUnitInfo;
            info.CommandParameter = unit;
            return info;
        }

        private static MenuItem GetMoveMenuItem(UnitInfo unit)
        {
            MenuItem move = new MenuItem();
            move.Header = "Move";
            move.Command = MoveCommand.Move;
            move.CommandParameter = unit;
            return move;
        }

        private static MenuItem GetBuildMenuItem(UnitInfo unit)
        {
            MenuItem build = new MenuItem();
            build.Header = "Build Settlement";
            build.Command = BuildCommand.Build;
            build.CommandParameter = unit;
            return build;
        }

        private static MenuItem GetExploreMenuItem(UnitInfo unit)
        {
            MenuItem explore = new MenuItem();
            explore.Header = "Explore";
            explore.Command = ExploreCommand.Explore;
            explore.CommandParameter = unit;
            return explore;
        }

        private static MenuItem GetFortifyMenuItem(UnitInfo unit)
        {
            MenuItem fortify = new MenuItem();
            fortify.Header = "Fortify";
            fortify.Command = FortifyCommand.Fortify;
            fortify.CommandParameter = unit;
            return fortify;
        }

        private static MenuItem GetDisbandMenuItem(UnitInfo unit)
        {
            MenuItem disband = new MenuItem();
            disband.Header = "Disband";
            disband.Command = DisbandCommand.Disband;
            disband.CommandParameter = unit;
            return disband;
        }

        private static MenuItem GetUpgradeMenuItem(UnitInfo unit)
        {
            MenuItem upgrade = new MenuItem();
            upgrade.Header = "Upgrade";
            upgrade.Command = UpgradeCommand.Upgrade;
            upgrade.CommandParameter = unit;
            return upgrade;
        }

        private static MenuItem GetAttackMenuItem(UnitInfo unit)
        {
            MenuItem attack = new MenuItem();
            attack.Header = "Attack";
            attack.Command = AttackCommand.Attack;
            attack.CommandParameter = unit;
            return attack;
        }
        #endregion
    }
}
